package com.richard.room.operator.api;

import android.annotation.SuppressLint;

import androidx.room.RoomDatabase;

import com.richard.room.operator.api.builder.OpBuilder;
import com.richard.room.operator.api.helper.SQLiteHelper;

import java.lang.reflect.Field;
import java.util.List;
import java.util.concurrent.Callable;

/**
 * @author: Richard
 * @createDate: 2023/8/8 11:08
 * @version: 1.0
 * @description: Room 数据操作
 */
public abstract class RoomOperator extends RoomDatabase {

    /**
     * Room数据库操作者
     */
    private static RoomOperator db;

    /**
     * 是否输出sql日志到控制台
     */
    public static boolean PRINT_SQL_LOG;

    protected RoomOperator() {
        db = this;
    }

    /**
     * 获取Room数据库操作者
     */
    public static RoomOperator db() {
        return db;
    }

    /**
     * 获取entity 信息
     */
    public abstract <T> Entity<T> getEntity(Class<T> entityClass);

    /**
     * 数据表操作
     *
     * @param entityClass 实体class
     */
    public static <T> OpBuilder<T> op(Class<T> entityClass) {
        return new OpBuilder<>(db, db.getEntity(entityClass));
    }

    /**
     * 事务中执行
     *
     * @param runnable 执行体
     */
    public static void runInTx(Runnable runnable) {
        db.runInTransaction(runnable);
    }

    /**
     * 事务中执行
     *
     * @param callable 带有返回结果的执行体
     */
    public static <T> T runInTx(Callable<T> callable) {
        return db.runInTransaction(callable);
    }

    /**
     * 根据sql语句查询结果集
     *
     * @param sql        sql语句
     * @param arguments  sql语句参数
     * @param resultType 查询结果数据泛型
     * @param <T>        结果集泛型
     * @return 结果集
     */
    public static <T> List<T> query(String sql, Object[] arguments, Class<T> resultType) {
        return SQLiteHelper.execQuerySql(db, sql, arguments, false, resultType);
    }

    /**
     * 根据sql查询一条数据
     *
     * @param sql        sql语句
     * @param arguments  sql语句参数
     * @param resultType 查询结果数据泛型
     * @param <T>        结果泛型
     * @return 结果
     */
    public static <T> T querySingleColumn(String sql, Object[] arguments, Class<T> resultType) {
        List<T> data = SQLiteHelper.execQuerySql(db, sql, arguments, true, resultType);
        return data != null && !data.isEmpty() ? data.get(0) : null;
    }

    /**
     * 设置CursorWindow 缓存大小，单位：字节
     * @return 返回的错误消息
     */
    public static String setCursorWindowSize(int sizeByte) {
        try {
            Class<?> clazz = Class.forName("android.database.CursorWindow");
            @SuppressLint("DiscouragedPrivateApi") Field field = clazz.getDeclaredField("sCursorWindowSize");
            field.setAccessible(true);
            field.set(null, sizeByte);
        } catch (Throwable e) {
            e.printStackTrace();
            return e.toString();
        }
        return null;
    }
}
